package com.hfzy.ihk.web.linkcall.biz;

import com.alibaba.fastjson.JSON;
import com.hfzy.ihk.common.core.elasticsearch.EsQueryUtils;
import com.hfzy.ihk.common.core.elasticsearch.service.EsBaseServiceImpl;
import com.hfzy.ihk.common.util.Utils;
import com.hfzy.ihk.common.util.string.StringUtil;
import com.hfzy.ihk.facade.linkcall.entity.task.CallTaskPhone;
import com.hfzy.ihk.facade.linkcall.enums.CallTaskStatus;
import com.hfzy.ihk.web.linkcall.dao.CallTaskPhoneRepository;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.RandomScoreFunctionBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.repository.ElasticsearchCrudRepository;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class CallTaskPhoneBiz extends EsBaseServiceImpl<CallTaskPhone> {
    Logger logger = LoggerFactory.getLogger(CallTaskPhoneBiz.class);

    @Autowired
    CallTaskPhoneRepository callTaskPhoneRepository;

    @Autowired
    CallTaskBiz callTaskBiz;

    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    protected ElasticsearchCrudRepository getReposity() {
        return this.callTaskPhoneRepository;
    }

    public boolean addCallTaskPhones(List<CallTaskPhone> callTaskPhoneList) {
        this.callTaskPhoneRepository.saveAll(callTaskPhoneList);
        return true;
    }

    /**
     * 随机获取
     */
    public CallTaskPhone getRandomPhoneByTaskId(String callTaskId)  {
        CallTaskPhone callTaskPhone = null;
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        QueryBuilder queryBuilder1 = EsQueryUtils.termQuery("callTaskId", callTaskId);
        QueryBuilder queryBuilder2 = EsQueryUtils.termQuery("hadCalled", false);
        boolQueryBuilder.must(queryBuilder1).must(queryBuilder2);
        //评分随机，由seed决定
        RandomScoreFunctionBuilder randomScoreFunctionBuilder = new RandomScoreFunctionBuilder();
        FunctionScoreQueryBuilder functionScoreQuery = new FunctionScoreQueryBuilder(EsQueryUtils.constantScoreQuery(boolQueryBuilder),randomScoreFunctionBuilder);
        Page<CallTaskPhone> callTaskPhonePage = callTaskPhoneRepository.search(functionScoreQuery,PageRequest.of(0, 1));

        /*Map<String,String> params = new HashMap();
        params.put("callTaskId",callTaskId);
        params.put("hadCalled","false");
        Page<CallTaskPhone> callTaskPhonePage = queryCallTaskPhonePage(params);*/
        if (callTaskPhonePage.getTotalElements() > 0) {
            callTaskPhone = Utils.getFirst(callTaskPhonePage.getContent());
            //取到后，更新已取
            callTaskPhone.setHadCalled(true);
            update(callTaskPhone);
        }else{
            //更新数据库
            Map<String, Object> updateMap = new HashMap<>();
            updateMap.put("status", CallTaskStatus.FINISHED);
            callTaskBiz.updateSomeFields(callTaskId,updateMap);
        }
        logger.info("随机获取号码：{}，{}", (callTaskId), (callTaskPhone != null ? callTaskPhone.getId() : "0"));
        return callTaskPhone;
    }

    public CallTaskPhone getCanCallTaskPhone(String callTaskId) {
        CallTaskPhone ctp = getRandomPhoneByTaskId(callTaskId);
        if(ctp!=null){//获取号码的次数+1
            callTaskBiz.addTakePhoneNum(callTaskId);
        }
        //判断号码是否已经外呼过3次？
        return ctp;
    }

    //aggsField 分组字段
    public long getCalledNum(Map<String,String> queryMap,String  aggsField){
        logger.debug("getCalledNum param:{}", JSON.toJSONString(queryMap));
        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilderByParams(queryMap);
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        /*if(!Utils.isNullString(aggsField)){
            //创建TermsBuilder对象，使用term查询，设置该分组的名称为aggs-class，并根据aggsField字段进行分组
            TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("orderByAggsField")//分组名称
                    .field(aggsField);//此处也可继续设置order、size等
            //添加分组信息
            nativeSearchQueryBuilder.addAggregation(termsAggregationBuilder);
        }*/

        SearchQuery searchQuery = nativeSearchQueryBuilder
                .withQuery(boolQueryBuilder).build();
        return  elasticsearchTemplate.count(searchQuery,CallTaskPhone.class);
    }


    public List<CallTaskPhone> queryCallTaskPhoneList(Map<String, String> params){
        logger.debug("queryCallTaskList param:{}", JSON.toJSONString(params));
        /*BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilderByParams(params);
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .build();
        return  elasticsearchTemplate.queryForList(searchQuery,CallTaskPhone.class);*/
        List<CallTaskPhone> callTaskPhones = null;
        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilderByParams(params);
        Iterator<CallTaskPhone> iterator = callTaskPhoneRepository.search(boolQueryBuilder).iterator();
        if (iterator != null) {
            callTaskPhones = new ArrayList<CallTaskPhone>();
            while (iterator.hasNext()) {
                CallTaskPhone next = iterator.next();
                callTaskPhones.add(next);
            }
        }
        return callTaskPhones;
    }


    public BoolQueryBuilder getBoolQueryBuilderByParams(Map<String, String> params) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        Iterator entries = params.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry entry = (Map.Entry) entries.next();
            String key = entry.getKey().toString();
            if (!StringUtil.isEmpty(entry.getValue().toString())) {
                switch (key) {
                    case "callTaskIds":
                        boolQueryBuilder.must(EsQueryUtils.termQuery("callTaskId", params.get("callTaskIds").split(",")));
                        break;
                    case "callTaskId":
                        boolQueryBuilder.must(EsQueryUtils.termQuery("callTaskId", params.get("callTaskId")));
                        break;
                    case "id":
                        QueryBuilder queryBuilder = EsQueryUtils.termQuery("id", params.get("id"));
                        boolQueryBuilder.must(queryBuilder);
                        break;
                    case "hadCalled":
                        boolQueryBuilder.must(EsQueryUtils.termQuery("hadCalled", Boolean.valueOf(params.get("hadCalled"))));
                        break;
                    default:
                        break;
                }
            }
        }
        return boolQueryBuilder;
    }

    public Page<CallTaskPhone> queryCallTaskPhonePage(Map<String, String> params) throws Exception {
        logger.debug("queryCallTaskPhonePage param:{}", JSON.toJSONString(params));
        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilderByParams(params);
        int pageNum = Integer.valueOf(params.get("page")) - 1;
        int pageSize = Integer.valueOf(params.get("pageSize"));
        //添加排序字段
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder).withPageable(PageRequest.of(pageNum, pageSize));
        return callTaskPhoneRepository.search(builder.build());
    }
}
